{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-03-09T14:33:21.367021Z",
     "start_time": "2018-03-09T22:33:12.637484+08:00"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n"
     ]
    }
   ],
   "source": [
    "import warnings\n",
    "warnings.filterwarnings(\"ignore\")\n",
    "\n",
    "from keras.optimizers import Adam, SGD, Nadam\n",
    "from keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau, TensorBoard, LearningRateScheduler\n",
    "from keras.callbacks import Callback\n",
    "from keras import backend as K \n",
    "from keras.models import load_model\n",
    "from math import ceil \n",
    "import numpy as np \n",
    "from termcolor import colored\n",
    "\n",
    "from mn_model import mn_model\n",
    "from face_generator import BatchGenerator\n",
    "from keras_ssd_loss import SSDLoss\n",
    "from ssd_box_encode_decode_utils import SSDBoxEncoder, decode_y, decode_y2\n",
    "\n",
    "# training parameters\n",
    "from keras import backend as K\n",
    "import scipy.misc as sm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-03-09T14:33:21.378011Z",
     "start_time": "2018-03-09T22:33:21.368987+08:00"
    }
   },
   "outputs": [],
   "source": [
    "img_height =512\n",
    "img_width = 512\n",
    "\n",
    "img_channels = 3\n",
    "\n",
    "n_classes =2 \n",
    "class_names = [\"background\",\"face\"]\n",
    "\n",
    "scales = [0.07, 0.15, 0.33, 0.51, 0.69, 0.87, 1.05] # anchorboxes for coco dataset\n",
    "aspect_ratios = [[0.5, 1.0, 2.0],\n",
    "                 [1.0/3.0, 0.5, 1.0, 2.0, 3.0],\n",
    "                 [1.0/3.0, 0.5, 1.0, 2.0, 3.0],\n",
    "                 [1.0/3.0, 0.5, 1.0, 2.0, 3.0],\n",
    "                 [0.5, 1.0, 2.0],\n",
    "                 [0.5, 1.0, 2.0]] # The anchor box aspect ratios used in the original SSD300\n",
    "two_boxes_for_ar1 = True\n",
    "limit_boxes = True # Whether or not you want to limit the anchor boxes to lie entirely within the image boundaries\n",
    "variances = [0.1, 0.1, 0.2, 0.2] # The variances by which the encoded target coordinates are scaled as in the original implementation\n",
    "coords = 'centroids' # Whether the box coordinates to be used as targets for the model should be in the 'centroids' or 'minmax' format, see documentation\n",
    "normalize_coords = True\n",
    "\n",
    "det_model_path = \"./models/\" "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-03-09T14:33:35.285228Z",
     "start_time": "2018-03-09T22:33:21.379013+08:00"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "====> Model Specific data\n",
      "====> Height, Width, Channels : 512 512 3\n",
      "Freezing classification layers\n",
      "classification layers freezed\n",
      "loading classification weights\n"
     ]
    }
   ],
   "source": [
    "train_data = 'wider_train_v1.npy'\n",
    "test_data = 'wider_val_v1.npy'\n",
    "\n",
    "\n",
    "# build the keras model\n",
    "# this model is not retrained, we are doing it from scratch \n",
    "\n",
    "K.clear_session()\n",
    "\n",
    "model, model_layer, img_input, predictor_sizes = mn_model(image_size=(img_height, img_width, img_channels), \n",
    "                                                                      n_classes = n_classes,\n",
    "                                                                      min_scale = None, \n",
    "                                                                      max_scale = None, \n",
    "                                                                      scales = scales, \n",
    "                                                                      aspect_ratios_global = None, \n",
    "                                                                      aspect_ratios_per_layer = aspect_ratios, \n",
    "                                                                      two_boxes_for_ar1= two_boxes_for_ar1, \n",
    "                                                                      limit_boxes=limit_boxes, \n",
    "                                                                      variances= variances, \n",
    "                                                                      coords=coords, \n",
    "                                                                      normalize_coords=normalize_coords)\n",
    "\n",
    "#model.summary()\n",
    "\n",
    "print (\"Freezing classification layers\")\n",
    "#Freeze layers\n",
    "for layer_key in model_layer:\n",
    "  if('detection'  not in layer_key): #prefix detection to freeze layers which does not have detection\n",
    "    model_layer[layer_key].trainable = False\n",
    "print (colored(\"classification layers freezed\", 'green'))\n",
    "\n",
    "# for layer in model.layers:\n",
    "#   print (colored(layer.name, 'blue'))\n",
    "#   print (colored(layer.trainable, 'green'))\n",
    "\n",
    "print (\"loading classification weights\")\n",
    "classification_model = './base_models/mobilenet_1_0_224_tf.h5'\n",
    "model.load_weights(classification_model,  by_name= True)\n",
    "\n",
    "# print (colored( ('classification weights %s loaded' % classification_model), 'green'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-03-09T14:36:54.861936Z",
     "start_time": "2018-03-09T22:33:35.286188+08:00"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "==>pretained model loaded successfully... \n",
      "==>TRAINING DATA\n",
      "==> Parsing XML files ...\n",
      "==>Parsing XML Finished.\n",
      "==>Generate training batches...\n",
      "==>Training batch generation complete\n",
      "==>Total number of training samples = 12620\n",
      "==>VALIDATION\n",
      "==> Parsing XML files ...\n",
      "==>Parsing XML Finished.\n",
      "==>Generate training batches...\n",
      "==>Training batch generation complete\n",
      "==>Total number of validation samples = 3143\n"
     ]
    }
   ],
   "source": [
    "# setting up taining \n",
    "\n",
    "batch_size = 64\n",
    "num_epochs = 10\n",
    "\n",
    "#Adam\n",
    "base_lr = 0.002\n",
    "adam = Adam(lr=base_lr, beta_1=0.9, beta_2=0.999, epsilon=1e-6, decay = 0.0)\n",
    "ssd_loss = SSDLoss(neg_pos_ratio=2, n_neg_min=0, alpha=1.0, beta = 1.0)\n",
    "model.compile(optimizer=adam, loss=ssd_loss.compute_loss)\n",
    "\n",
    "# SGD\n",
    "# base_lr = 0.002\n",
    "# momentum = 0.9\n",
    "# decay = 0.0005\n",
    "# sgd = SGD(lr=base_lr, momentum=momentum, decay=decay, nesterov=True)\n",
    "# ssd_loss = SSDLoss(neg_pos_ratio=2, n_neg_min=0, alpha=1.0, beta = 1.0)\n",
    "# model.compile(optimizer=sgd, loss=ssd_loss.compute_loss)\n",
    "\n",
    "\n",
    "print (\"==>pretained model loaded successfully... \")\n",
    "\n",
    "\n",
    "ssd_box_encoder = SSDBoxEncoder(img_height=img_height,\n",
    "                                img_width=img_width,\n",
    "                                n_classes=n_classes, \n",
    "                                predictor_sizes=predictor_sizes,\n",
    "                                min_scale=None,\n",
    "                                max_scale=None,\n",
    "                                scales=scales,\n",
    "                                aspect_ratios_global=None,\n",
    "                                aspect_ratios_per_layer=aspect_ratios,\n",
    "                                two_boxes_for_ar1=two_boxes_for_ar1,\n",
    "                                limit_boxes=limit_boxes,\n",
    "                                variances=variances,\n",
    "                                pos_iou_threshold=0.5,\n",
    "                                neg_iou_threshold=0.2,\n",
    "                                coords=coords,\n",
    "                                normalize_coords=normalize_coords)\n",
    "\n",
    "train_dataset = BatchGenerator(images_path=train_data, \n",
    "                include_classes='all', \n",
    "                box_output_format = ['class_id', 'xmin', 'xmax', 'ymin', 'ymax'])\n",
    "\n",
    "print (\"==>TRAINING DATA\")\n",
    "print (\"==> Parsing XML files ...\")\n",
    "\n",
    "train_dataset.parse_xml(\n",
    "                  annotations_path=train_data,\n",
    "                  image_set_path='None',\n",
    "                  image_set='None',\n",
    "                  classes = class_names, \n",
    "                  exclude_truncated=False,\n",
    "                  exclude_difficult=False,\n",
    "                  ret=False, \n",
    "                  debug = False)\n",
    "print(\"==>Parsing XML Finished.\")\n",
    "\n",
    "print (\"==>Generate training batches...\")\n",
    "train_generator = train_dataset.generate(\n",
    "                 batch_size=batch_size,\n",
    "                 train=True,\n",
    "                 ssd_box_encoder=ssd_box_encoder,\n",
    "                 equalize=True,\n",
    "                 brightness=(0.5,2,0.5),\n",
    "                 flip=0.5,\n",
    "                 translate=((0, 20), (0, 30), 0.5),\n",
    "                 scale=(0.75, 1.2, 0.5),\n",
    "                 crop=False,\n",
    "                 #random_crop = (img_height,img_width,1,3), \n",
    "                 random_crop=False,\n",
    "                 resize=(img_height, img_width),\n",
    "                 #resize=False,\n",
    "                 gray=False,\n",
    "                 limit_boxes=True,\n",
    "                 include_thresh=0.4,\n",
    "                 diagnostics=False)\n",
    "\n",
    "print (\"==>Training batch generation complete\")\n",
    "\n",
    "n_train_samples = train_dataset.get_n_samples()\n",
    "\n",
    "print (\"==>Total number of training samples = {}\".format(n_train_samples))\n",
    "\n",
    "# Now repeat above steps for validation data \n",
    "\n",
    "print (\"==>VALIDATION\")\n",
    "\n",
    "val_dataset = BatchGenerator(images_path=test_data, include_classes='all', \n",
    "                box_output_format = ['class_id', 'xmin', 'xmax', 'ymin', 'ymax'])\n",
    "\n",
    "print (\"==> Parsing XML files ...\")\n",
    "\n",
    "\n",
    "val_dataset.parse_xml(\n",
    "                  annotations_path=test_data,\n",
    "                  image_set_path='None',\n",
    "                  image_set='None',\n",
    "                  classes = class_names, \n",
    "                  exclude_truncated=False,\n",
    "                  exclude_difficult=False,\n",
    "                  ret=False, \n",
    "                  debug = False)\n",
    "\n",
    "\n",
    "print(\"==>Parsing XML Finished.\")\n",
    "\n",
    "\n",
    "print (\"==>Generate training batches...\")\n",
    "val_generator = val_dataset.generate(\n",
    "                 batch_size=batch_size,\n",
    "                 train=True,\n",
    "                 ssd_box_encoder=ssd_box_encoder,\n",
    "                 equalize=False,\n",
    "                 brightness=False,\n",
    "                 flip=False,\n",
    "                 translate=False,\n",
    "                 scale=False,\n",
    "                 crop=False,\n",
    "                 #random_crop = (img_height,img_width,1,3), \n",
    "                 random_crop=False, \n",
    "                 resize=(img_height, img_width), \n",
    "                 #resize=False, \n",
    "                 gray=False,\n",
    "                 limit_boxes=True,\n",
    "                 include_thresh=0.4,\n",
    "                 diagnostics=False)\n",
    "\n",
    "\n",
    "print (\"==>Training batch generation complete\")\n",
    "\n",
    "n_val_samples = val_dataset.get_n_samples()\n",
    "\n",
    "print (\"==>Total number of validation samples = {}\".format(n_val_samples))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-03-09T14:40:49.615390Z",
     "start_time": "2018-03-09T22:36:54.863941+08:00"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "training starting...\n",
      "Epoch 1/10\n",
      "lr remains 0.0020000000949949026\n",
      " 69/396 [====>.........................] - ETA: 1:13:43 - loss: 0.19 - ETA: 41:53 - loss: 0.1893 - ETA: 36:54 - loss: 0.18 - ETA: 34:04 - loss: 0.18 - ETA: 32:07 - loss: 0.17 - ETA: 30:41 - loss: 0.17 - ETA: 29:07 - loss: 0.16 - ETA: 27:59 - loss: 0.16 - ETA: 27:09 - loss: 0.16 - ETA: 26:19 - loss: 0.16 - ETA: 25:43 - loss: 0.16 - ETA: 25:15 - loss: 0.15 - ETA: 24:48 - loss: 0.15 - ETA: 24:23 - loss: 0.15 - ETA: 24:04 - loss: 0.15 - ETA: 23:40 - loss: 0.15 - ETA: 23:17 - loss: 0.15 - ETA: 23:01 - loss: 0.14 - ETA: 22:41 - loss: 0.14 - ETA: 22:28 - loss: 0.14 - ETA: 22:15 - loss: 0.14 - ETA: 22:00 - loss: 0.14 - ETA: 21:48 - loss: 0.14 - ETA: 21:33 - loss: 0.14 - ETA: 21:23 - loss: 0.14 - ETA: 21:11 - loss: 0.14 - ETA: 21:02 - loss: 0.14 - ETA: 20:50 - loss: 0.14 - ETA: 20:43 - loss: 0.13 - ETA: 20:33 - loss: 0.13 - ETA: 20:26 - loss: 0.13 - ETA: 20:21 - loss: 0.13 - ETA: 20:12 - loss: 0.13 - ETA: 20:05 - loss: 0.13 - ETA: 20:02 - loss: 0.13 - ETA: 19:57 - loss: 0.13 - ETA: 19:49 - loss: 0.13 - ETA: 19:45 - loss: 0.13 - ETA: 19:38 - loss: 0.13 - ETA: 19:33 - loss: 0.13 - ETA: 19:28 - loss: 0.13 - ETA: 19:24 - loss: 0.13 - ETA: 19:20 - loss: 0.13 - ETA: 19:14 - loss: 0.13 - ETA: 19:08 - loss: 0.12 - ETA: 19:05 - loss: 0.12 - ETA: 19:02 - loss: 0.12 - ETA: 18:56 - loss: 0.12 - ETA: 18:53 - loss: 0.12 - ETA: 18:48 - loss: 0.12 - ETA: 18:43 - loss: 0.12 - ETA: 18:39 - loss: 0.12 - ETA: 18:34 - loss: 0.12 - ETA: 18:29 - loss: 0.12 - ETA: 18:25 - loss: 0.12 - ETA: 18:23 - loss: 0.12 - ETA: 18:19 - loss: 0.12 - ETA: 18:16 - loss: 0.12 - ETA: 18:12 - loss: 0.12 - ETA: 18:08 - loss: 0.12 - ETA: 18:04 - loss: 0.12 - ETA: 18:00 - loss: 0.12 - ETA: 17:57 - loss: 0.12 - ETA: 17:53 - loss: 0.12 - ETA: 17:48 - loss: 0.12 - ETA: 17:46 - loss: 0.12 - ETA: 17:41 - loss: 0.12 - ETA: 17:38 - loss: 0.12 - ETA: 17:34 - loss: 0.1224"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-5-3c8122ee7f85>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m     32\u001b[0m                               \u001b[0mcallbacks\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mmodel_checkpoint\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mlr_schedule\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mearly_stopping\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m     33\u001b[0m                               \u001b[0mvalidation_data\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mval_generator\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m---> 34\u001b[0;31m                               validation_steps = ceil(n_val_samples/batch_size))\n\u001b[0m\u001b[1;32m     35\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m     36\u001b[0m \u001b[0mmodel\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msave_weights\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdet_model_path\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;34m'ssd_mobilenet_weights_epoch_{}.h5'\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mepochs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[0;32mc:\\users\\zjuyang\\anaconda3\\lib\\site-packages\\keras\\legacy\\interfaces.py\u001b[0m in \u001b[0;36mwrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m     89\u001b[0m                 warnings.warn('Update your `' + object_name +\n\u001b[1;32m     90\u001b[0m                               '` call to the Keras 2 API: ' + signature, stacklevel=2)\n\u001b[0;32m---> 91\u001b[0;31m             \u001b[1;32mreturn\u001b[0m \u001b[0mfunc\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     92\u001b[0m         \u001b[0mwrapper\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_original_function\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m     93\u001b[0m         \u001b[1;32mreturn\u001b[0m \u001b[0mwrapper\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[0;32mc:\\users\\zjuyang\\anaconda3\\lib\\site-packages\\keras\\engine\\training.py\u001b[0m in \u001b[0;36mfit_generator\u001b[0;34m(self, generator, steps_per_epoch, epochs, verbose, callbacks, validation_data, validation_steps, class_weight, max_queue_size, workers, use_multiprocessing, shuffle, initial_epoch)\u001b[0m\n\u001b[1;32m   2210\u001b[0m                 \u001b[0mbatch_index\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m   2211\u001b[0m                 \u001b[1;32mwhile\u001b[0m \u001b[0msteps_done\u001b[0m \u001b[1;33m<\u001b[0m \u001b[0msteps_per_epoch\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2212\u001b[0;31m                     \u001b[0mgenerator_output\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnext\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0moutput_generator\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   2213\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m   2214\u001b[0m                     \u001b[1;32mif\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0mhasattr\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mgenerator_output\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'__len__'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[0;32mc:\\users\\zjuyang\\anaconda3\\lib\\site-packages\\keras\\utils\\data_utils.py\u001b[0m in \u001b[0;36mget\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m    771\u001b[0m                     \u001b[1;32mraise\u001b[0m \u001b[0mStopIteration\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m    772\u001b[0m                 \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 773\u001b[0;31m                     \u001b[0mtime\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msleep\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mwait_time\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    774\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m    775\u001b[0m         \u001b[1;31m# Make sure to rethrow the first exception in the queue, if any\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m: "
     ]
    }
   ],
   "source": [
    "# now start the training \n",
    "\n",
    "def scheduler(epoch):\n",
    "  if epoch%10==0 and epoch!=0:\n",
    "  #if epoch !=0 or epp:\n",
    "    lr = K.get_value(model.optimizer.lr)\n",
    "    K.set_value(model.optimizer.lr, lr*.95)\n",
    "    print(\"lr changed to {}\".format(lr*.95))\n",
    "  else: \n",
    "    print(\"lr remains {}\".format(K.get_value(model.optimizer.lr)))\n",
    "\n",
    "  return K.get_value(model.optimizer.lr)\n",
    "\n",
    "lr_schedule = LearningRateScheduler(scheduler)\n",
    "\n",
    "plateau = ReduceLROnPlateau(monitor='val_loss', factor = 0.3, patience =4, epsilon=0.001, cooldown=0)\n",
    "tensorboard = TensorBoard(log_dir='./logs/trial1/', histogram_freq=1, batch_size=16, write_graph=True, write_grads=True, \n",
    "                          write_images=True, embeddings_freq=0, embeddings_layer_names=None, embeddings_metadata=None)\n",
    "early_stopping = EarlyStopping(monitor='val_loss', min_delta=0.001, patience=100)\n",
    "model_checkpoint =  ModelCheckpoint(det_model_path + 'ssd_mobilenet_face_epoch_{epoch:02d}_loss{val_loss:.4f}.h5',\n",
    "                                                           monitor='val_loss',\n",
    "                                                           verbose=1,\n",
    "                                                           save_best_only=True,\n",
    "                                                           save_weights_only=True,\n",
    "                                                           mode='auto',\n",
    "                                                           period=1)\n",
    "\n",
    "print (\"training starting...\")\n",
    "history = model.fit_generator(generator = train_generator,\n",
    "                              steps_per_epoch = ceil(n_train_samples/batch_size)*2,\n",
    "                              epochs = num_epochs,\n",
    "                              callbacks = [model_checkpoint, lr_schedule, early_stopping],                      \n",
    "                              validation_data = val_generator,\n",
    "                              validation_steps = ceil(n_val_samples/batch_size))\n",
    "\n",
    "model.save_weights(det_model_path + 'ssd_mobilenet_weights_epoch_{}.h5'.format(epochs))\n",
    "\n",
    "print (\"model and weight files saved at : \" + det_model_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-03-09T15:11:52.562338Z",
     "start_time": "2018-03-09T23:11:52.383835+08:00"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "weights ./models/ssd_mobilenet_face_epoch_25_loss0.0916.h5 loaded\n"
     ]
    }
   ],
   "source": [
    "model_path = './models/'\n",
    "model_name = 'ssd_mobilenet_face_epoch_25_loss0.0916.h5'\n",
    "\n",
    "model.load_weights(model_path + model_name,  by_name= True)\n",
    "\n",
    "print (colored('weights %s loaded' % (model_path + model_name), 'green'))\n",
    "\n",
    "def save_bb(path, filename, results, prediction=True):\n",
    "  \n",
    "  # print filename\n",
    "\n",
    "  img = image.load_img(filename, target_size=(img_height, img_width))\n",
    "  img = image.img_to_array(img)\n",
    "\n",
    "  filename = filename.split(\"/\")[-1]\n",
    "\n",
    "  if(not prediction):\n",
    "    filename = filename[:-4] + \"_gt\" + \".jpg\"\n",
    "\n",
    "  #fig,currentAxis = plt.subplots(1)\n",
    "  currentAxis = plt.gca()\n",
    "\n",
    " # Get detections with confidence higher than 0.6.\n",
    "  colors = plt.cm.hsv(np.linspace(0, 1, 25)).tolist()\n",
    "  color_code = min(len(results), 16)\n",
    "  print (colored(\"total number of bbs: %d\" % len(results), \"yellow\"))\n",
    "  for result in results:\n",
    "    # Parse the outputs.\n",
    "\n",
    "    if(prediction):\n",
    "      det_label = result[0]\n",
    "      det_conf = result[1]\n",
    "      det_xmin = result[2]\n",
    "      det_xmax = result[3]\n",
    "      det_ymin = result[4]\n",
    "      det_ymax = result[5]\n",
    "    else :\n",
    "      det_label = result[0]\n",
    "      det_xmin = result[1]\n",
    "      det_xmax = result[2]\n",
    "      det_ymin = result[3]\n",
    "      det_ymax = result[4]\n",
    "\n",
    "    xmin = int(det_xmin)\n",
    "    ymin = int(det_ymin)\n",
    "    xmax = int(det_xmax)\n",
    "    ymax = int(det_ymax)\n",
    "\n",
    "    if(prediction):\n",
    "      score = det_conf\n",
    "    \n",
    "    plt.imshow(img / 255.)\n",
    "    \n",
    "    label = int(int(det_label))\n",
    "    label_name = class_names[label]\n",
    "    # print label_name \n",
    "    # print label\n",
    "\n",
    "    if(prediction):\n",
    "      display_txt = '{:0.2f}'.format(score)\n",
    "    else:\n",
    "      display_txt = '{}'.format(label_name)\n",
    "\n",
    "      \n",
    "    # print (xmin, ymin, ymin, ymax)\n",
    "    coords = (xmin, ymin), (xmax-xmin), (ymax-ymin)\n",
    "    color_code = color_code-1 \n",
    "    color = colors[color_code]\n",
    "    currentAxis.add_patch(plt.Rectangle(*coords, fill=False, edgecolor=color, linewidth=2))\n",
    "    currentAxis.text(xmin, ymin, display_txt, bbox={'facecolor':color, 'alpha':0.2})\n",
    "\n",
    "  # y 轴不可见\n",
    "  currentAxis.axes.get_yaxis().set_visible(False)\n",
    "  # x 轴不可见\n",
    "  currentAxis.axes.get_xaxis().set_visible(False)\n",
    "  plt.savefig(path + filename, bbox_inches='tight')\n",
    "\n",
    "  print ('saved' , path + filename)\n",
    "\n",
    "  plt.clf()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-03-09T15:42:25.277298Z",
     "start_time": "2018-03-09T23:42:06.631484+08:00"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "done.\n",
      "now predicting...\n",
      "total number of bbs: 11\n",
      "saved ./output_test/35_Basketball_Basketball_35_361.jpg\n",
      "total number of bbs: 16\n",
      "saved ./output_test/35_Basketball_Basketball_35_361_gt.jpg\n",
      "total number of bbs: 1\n",
      "saved ./output_test/24_Soldier_Firing_Soldier_Firing_24_887.jpg\n",
      "total number of bbs: 1\n",
      "saved ./output_test/24_Soldier_Firing_Soldier_Firing_24_887_gt.jpg\n",
      "total number of bbs: 7\n",
      "saved ./output_test/38_Tennis_Tennis_38_683.jpg\n",
      "total number of bbs: 7\n",
      "saved ./output_test/38_Tennis_Tennis_38_683_gt.jpg\n",
      "total number of bbs: 3\n",
      "saved ./output_test/5_Car_Accident_Accident_5_244.jpg\n",
      "total number of bbs: 10\n",
      "saved ./output_test/5_Car_Accident_Accident_5_244_gt.jpg\n",
      "total number of bbs: 0\n",
      "saved ./output_test/23_Shoppers_Shoppers_23_450.jpg\n",
      "total number of bbs: 3\n",
      "saved ./output_test/23_Shoppers_Shoppers_23_450_gt.jpg\n",
      "total number of bbs: 4\n",
      "saved ./output_test/0_Parade_marchingband_1_822.jpg\n",
      "total number of bbs: 6\n",
      "saved ./output_test/0_Parade_marchingband_1_822_gt.jpg\n",
      "total number of bbs: 2\n",
      "saved ./output_test/35_Basketball_Basketball_35_185.jpg\n",
      "total number of bbs: 4\n",
      "saved ./output_test/35_Basketball_Basketball_35_185_gt.jpg\n",
      "total number of bbs: 6\n",
      "saved ./output_test/3_Riot_Riot_3_725.jpg\n",
      "total number of bbs: 16\n",
      "saved ./output_test/3_Riot_Riot_3_725_gt.jpg\n",
      "total number of bbs: 4\n",
      "saved ./output_test/3_Riot_Riot_3_604.jpg\n",
      "total number of bbs: 4\n",
      "saved ./output_test/3_Riot_Riot_3_604_gt.jpg\n",
      "total number of bbs: 1\n",
      "saved ./output_test/13_Interview_Interview_Sequences_13_864.jpg\n",
      "total number of bbs: 4\n",
      "saved ./output_test/13_Interview_Interview_Sequences_13_864_gt.jpg\n",
      "total number of bbs: 4\n",
      "saved ./output_test/0_Parade_Parade_0_353.jpg\n",
      "total number of bbs: 11\n",
      "saved ./output_test/0_Parade_Parade_0_353_gt.jpg\n",
      "total number of bbs: 1\n",
      "saved ./output_test/13_Interview_Interview_Sequences_13_270.jpg\n",
      "total number of bbs: 1\n",
      "saved ./output_test/13_Interview_Interview_Sequences_13_270_gt.jpg\n",
      "total number of bbs: 4\n",
      "saved ./output_test/52_Photographers_photographertakingphoto_52_316.jpg\n",
      "total number of bbs: 3\n",
      "saved ./output_test/52_Photographers_photographertakingphoto_52_316_gt.jpg\n",
      "total number of bbs: 2\n",
      "saved ./output_test/44_Aerobics_Aerobics_44_809.jpg\n",
      "total number of bbs: 3\n",
      "saved ./output_test/44_Aerobics_Aerobics_44_809_gt.jpg\n",
      "total number of bbs: 2\n",
      "saved ./output_test/20_Family_Group_Family_Group_20_193.jpg\n",
      "total number of bbs: 3\n",
      "saved ./output_test/20_Family_Group_Family_Group_20_193_gt.jpg\n",
      "total number of bbs: 9\n",
      "saved ./output_test/2_Demonstration_Demonstration_Or_Protest_2_441.jpg\n",
      "total number of bbs: 18\n",
      "saved ./output_test/2_Demonstration_Demonstration_Or_Protest_2_441_gt.jpg\n"
     ]
    }
   ],
   "source": [
    "from keras.preprocessing import image\n",
    "from matplotlib import pyplot as plt\n",
    "\n",
    "test_size = 16\n",
    "test_generator = val_dataset.generate(\n",
    "                 batch_size=test_size,\n",
    "                 train=False,\n",
    "                 ssd_box_encoder=ssd_box_encoder,\n",
    "                 equalize=False,\n",
    "                 brightness=False,\n",
    "                 flip=False,\n",
    "                 translate=False,\n",
    "                 scale=False,\n",
    "                 crop=False,\n",
    "                 #random_crop = (img_height,img_width,1,3), \n",
    "                 random_crop=False, \n",
    "                 resize=(img_height, img_width), \n",
    "                 #resize=False,\n",
    "                 gray=False,\n",
    "                 limit_boxes=True,\n",
    "                 include_thresh=0.4,\n",
    "                 diagnostics=False)\n",
    "\n",
    "print (colored(\"done.\", \"green\"))\n",
    "\n",
    "print (colored(\"now predicting...\", \"yellow\"))\n",
    "\n",
    "_CONF = 0.60 \n",
    "_IOU = 0.15\n",
    "\n",
    "for i in range(test_size):\n",
    "  X, y, filenames = next(test_generator)\n",
    "\n",
    "  y_pred = model.predict(X)\n",
    "\n",
    "\n",
    "  y_pred_decoded = decode_y2(y_pred,\n",
    "                             confidence_thresh=_CONF,\n",
    "                            iou_threshold=_IOU,\n",
    "                            top_k='all',\n",
    "                            input_coords=coords,\n",
    "                            normalize_coords=normalize_coords,\n",
    "                            img_height=img_height,\n",
    "                            img_width=img_width)\n",
    "\n",
    "\n",
    "  np.set_printoptions(suppress=True)\n",
    "\n",
    "  save_bb(\"./output_test/\", filenames[i], y_pred_decoded[i])\n",
    "  save_bb(\"./output_test/\", filenames[i], y[i], prediction=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python [default]",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
